//
//  VNCView.m
//  vnsea
//
//  Created by Chris Reed on 9/5/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
// Modified by: Glenn Kreisel

#import "VNCView.h"
#import "VNCPopupView.h"
#import "VnseaApp.h"
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKit.h>
#import <UIKit/UITextView.h>
#import <UIKit/UITouchDiagnosticsLayer.h>
#import <UIKit/UINavBarButton.h>
#import <UIKit/UIView-Gestures.h>
#import <UIKit/UIKeyboardImpl.h>
#import <UIKit/UIView-Deprecated.h>
#import <UIKit/UIKeyboardLayoutQWERTY.h>
#import <UIKit/UIKeyboardLayoutQWERTYLandscape.h>
#import <UIKit/UITextView.h>
#import <UIKit/UITextTraits.h>
#import <GraphicsServices/GraphicsServices.h>
#import "RectangleList.h"
#import "QueuedEvent.h"
#import "VNCPreferences.h"

//! Height of the controls bar view.
#define kControlsBarHeight (48.0f)

//! Height of buttons in the controls bar.
#define kControlsBarButtonHeight (32.0f)

#define kKeyboardButtonWidth (40.0f)
#define kExitButtonWidth (28.0f)
#define kRightMouseButtonWidth (28.0f)
#define kModifierKeyButtonWidth (28.0f)

#define kModifierKeyImageWidth (21.0f)
#define kModifierKeyImageHeight (21.0f)

#define kButtonSpacing (5.0f)

// There's got to be a better way to do this, but for now this is just fine.
// Thanks to the MobileTerminal team for this trick.
@implementation UIKeyboardImpl (DisableFeatures)

- (BOOL)autoCapitalizationPreference
{
	return NO;
}

- (BOOL)autoCorrectionPreference
{
	return NO;
}

@end

@implementation VNCView

- (void)acceleratedInX:(float)xx Y:(float)yy Z:(float)zz
{
	[_filter acceleratedInX:xx Y:yy Z:zz];
}

- (void)startSendingArrowKeys:(id)sender
{
	[self sendArrowKeys: sender];
	[self stopSendingArrowKeys: sender];
	_keySendTimer = [[NSTimer scheduledTimerWithTimeInterval:.5 target:self selector:@selector(handleKeySendTimer:) userInfo:(id)sender repeats:NO] retain];
}

- (void)handleKeySendTimer:(NSTimer *)timer
{
	id sender = (id)[timer userInfo];
	[self stopSendingArrowKeys: sender];
	_keySendTimer = [[NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(handleKeySendTimerRepeater:) userInfo:(id) sender repeats:YES] retain];
}

- (void)handleKeySendTimerRepeater:(NSTimer *)timer
{
	[self sendArrowKeys: (id)[timer userInfo]];
}

- (void)stopSendingArrowKeys:(id)sender
{
	if (_keySendTimer)
	{
		[_keySendTimer invalidate];
		[_keySendTimer release];
		_keySendTimer = nil;
	}
}

- (void)sendArrowKeys:(id)sender
{
	UIPushButton *pb = (UIPushButton *)sender;
	NSString *ns = [pb title];
	[_connection sendArrowKey: ns];
}

- (void)sendFunctionKeys:(id)sender
{
	UIPushButton *pb = (UIPushButton *)sender;
	NSString *ns;
	
	ns = [[pb title] substringFromIndex:1];
	NSLog(@"Numbers equal %@", ns);
	NSLog(@"Numbers int equal %d", [ns intValue]);
	
	[_connection sendFunctionKey: (unsigned)[ns intValue]];
}

- (void)sendESCKey:(id)sender
{	
	[_connection sendEscapeKey];
}

- (void)sendTabKey:(id)sender
{	
	[_connection sendTabKey];
}

- (void)sendCtrlAltDel:(id)sender
{
	[_connection sendCtrlAltDel:nil];
}

- (void)sendFullRefresh:(id)sender
{
	[_connection sendFullScreenRefresh];
}

// I can never remember this relationship for some reason:
// The frame rectangle defines the view's location and size in the superview using the superview’s coordinate system. The bounds rectangle defines the interior coordinate system that is used when drawing the contents of the view, including the origin and scaling.
- (id)initWithFrame:(CGRect)frame
{
	if ([super initWithFrame:frame])
	{
		CGRect subframe = frame;
		subframe.origin = CGPointMake(0, 0);
		
		// Create scroller view.
		_scroller = [[VNCScrollerView alloc] initWithFrame:subframe];
		[_scroller setVNCView: self];
		[_scroller setScrollingEnabled:YES];
		[_scroller setShowScrollerIndicators:YES];
		[_scroller setAdjustForContentSizeChange:NO];
		[_scroller setAllowsRubberBanding:YES];
		[_scroller setAllowsFourWayRubberBanding:YES];
		[_scroller setRubberBand: 50 forEdges:0];
		[_scroller setRubberBand: 50 forEdges:1];
		[_scroller setRubberBand: 50 forEdges:2];
		[_scroller setRubberBand: 50 forEdges:3];
		[_scroller setDelegate:self];
		
		// Create controls bar.
		[self layoutControlsBar];
		
		// Create screen view.
		_screenView = [[VNCContentView alloc] initWithFrame:subframe];
		[_screenView setDelegate: [self delegate]];
	
		// Set our background color to black.
		const float kBlackComponents[] = { 0, 0, 0, 1 };
		CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
		CGColorRef black = CGColorCreate(rgbSpace, kBlackComponents);
		CGColorSpaceRelease(rgbSpace);
		
		[self setOpaque:YES];
		[self setBackgroundColor:black];
		
		// Build view hierarchy.
		[self addSubview:_controlsView];
		[_scroller addSubview:_screenView];
		[self addSubview:_scroller];
		
		// Init some instance variables.
		_areControlsVisible = NO;
		_isKeyboardVisible = NO;
		_scaleState = kScaleFitNone;
		_ipodScreenSize = CGSizeMake(frame.size.width, frame.size.height);
	}
	
	return self;
}

//! This method creates the controls bar that appears at the bottom of the display
//! in portrait mode, as well as all of the buttons within it.
- (void)layoutControlsBar
{
	CGRect frame = [self frame];
	// Create control bar, initially just below the bottom of the screen.
	CGRect subframe = CGRectMake(0, frame.size.height, frame.size.width, kControlsBarHeight);
	_controlsView = [[UIGradientBar alloc] initWithFrame:subframe];
	
	[self initControlsBar];
}

- (void)initControlsBar
{
	CGRect frame = [self frame], subframe;
	bool bUseTextIcons = [[VNCPreferences sharedPreferences] useTextIcons];
	
	if (_keyboardButton)
	{
		[_keyboardButton removeFromSuperview];
		[_exitButton removeFromSuperview];
		[_shiftButton removeFromSuperview];
		[_commandButton removeFromSuperview];
		[_optionButton removeFromSuperview];
		[_controlButton removeFromSuperview];
		[_helperFunctionButton removeFromSuperview];
		[_rightMouseButton removeFromSuperview];
		[_keyboardButton release];
		[_exitButton release];
		[_shiftButton release];
		[_commandButton release];
		[_optionButton release];
		[_controlButton release];
		[_helperFunctionButton release];
		[_rightMouseButton release];
		_keyboardButton = nil;
		_exitButton = nil;
		_shiftButton = nil;
		_commandButton = nil;
		_optionButton = nil;
		_controlButton = nil;
		_helperFunctionButton = nil;
		_rightMouseButton = nil;
	}

	
	// Create keyboard button.
	subframe = CGRectMake(5, (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kKeyboardButtonWidth, kControlsBarButtonHeight);
	_keyboardButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"keyboard.png"]];
	[_keyboardButton setFrame:subframe];
	[_keyboardButton setNavBarButtonStyle:0];
	[_optionButton setDrawContentsCentered:YES];
	[_keyboardButton addTarget:self action:@selector(toggleKeyboard:) forEvents:kUIControlEventMouseUpInside];
	
	// Modifier key buttons.
	subframe = CGRectMake(CGRectGetMaxX(subframe) + kButtonSpacing, (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kModifierKeyButtonWidth, kControlsBarButtonHeight);
	if (bUseTextIcons)
		_shiftButton = [[UINavBarButton alloc] initWithTitle:@"Sh"];
	else
		_shiftButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"shift_key.png"]];
	[_shiftButton setFrame:subframe];
	[_shiftButton setNavBarButtonStyle:0];
	[_optionButton setDrawContentsCentered:YES];
	[_shiftButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	subframe.origin.x = CGRectGetMaxX(subframe) + kButtonSpacing;
	if (bUseTextIcons)
		_controlButton = [[UINavBarButton alloc] initWithTitle:@"Ctl"];
	else
		_controlButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"ctrl_key.png"]];
	[_controlButton setFrame:subframe];
	[_controlButton setNavBarButtonStyle:0];
	[_controlButton setDrawContentsCentered:YES];
	[_controlButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	subframe.origin.x = CGRectGetMaxX(subframe) + kButtonSpacing;
	if (bUseTextIcons)
		_commandButton = [[UINavBarButton alloc] initWithTitle:@"Alt"];
	else
		_commandButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"cmd_key.png"]];
	[_commandButton setFrame:subframe];
	[_commandButton setNavBarButtonStyle:0];
	[_commandButton setDrawContentsCentered:YES];
	[_commandButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	subframe.origin.x = CGRectGetMaxX(subframe) + kButtonSpacing;
	if (bUseTextIcons)
		_optionButton = [[UINavBarButton alloc] initWithTitle:@"Op"];
	else
		_optionButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"opt_key.png"]];
	[_optionButton setFrame:subframe];
	[_optionButton setNavBarButtonStyle:0];
	[_optionButton setDrawContentsCentered:YES];
	[_optionButton addTarget:self action:@selector(toggleModifierKey:) forEvents:kUIControlEventMouseUpInside];
	
	// Helper Functions "more" button on the status bar
	subframe = CGRectMake(subframe.origin.x + kModifierKeyButtonWidth + 5 , (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, 58, kControlsBarButtonHeight);
	_helperFunctionButton = [[UINavBarButton alloc] initWithTitle:@"Remote"];
	[_helperFunctionButton setFrame:subframe];
	[_helperFunctionButton setNavBarButtonStyle:0];
	[_helperFunctionButton setDrawContentsCentered:YES];
	[_helperFunctionButton addTarget:self action:@selector(toggleRemote:) forEvents:kUIControlEventMouseUpInside];

	// Right mouse button.
	subframe = CGRectMake(frame.size.width - kExitButtonWidth - 5 - kRightMouseButtonWidth - 6 - 8, (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kRightMouseButtonWidth, kControlsBarButtonHeight);
//	_rightMouseButton = [[UINavBarButton alloc] initWithImage:[UIImage imageNamed:@"right_mouse.png"]]; //WithTitle:@"W" autosizesToFit:NO];
	_rightMouseButton = [[UINavBarButton alloc] initWithTitle:@"?" autosizesToFit:NO];
	[_rightMouseButton setTitleFont:GSFontCreateWithName("VerdanaBold", 0, 19.0f)];
	[_rightMouseButton setFrame:subframe];
	[_rightMouseButton setNavBarButtonStyle:0];
	[_rightMouseButton setDrawContentsCentered:YES];
	[_rightMouseButton addTarget:self action:@selector(getHelp:) forEvents:kUIControlEventMouseUpInside];
	
	// Terminate connection button.
	subframe = CGRectMake(frame.size.width - kExitButtonWidth - 5, (kControlsBarHeight - kControlsBarButtonHeight) / 2.0f + 1.0f, kExitButtonWidth, kControlsBarButtonHeight);
	_exitButton = [[UINavBarButton alloc] initWithTitle:@"X" autosizesToFit:NO];
	[_exitButton setTitleFont:GSFontCreateWithName("VerdanaBold", 0, 19.0f)];
	[_exitButton setFrame:subframe];
	[_exitButton setNavBarButtonStyle:0];
	[_exitButton setDrawContentsCentered:YES];
	[_exitButton addTarget:self action:@selector(closeConnection:) forEvents:kUIControlEventMouseUpInside];
	
	// Build controls bar view hierarchy.
	[_controlsView addSubview:_keyboardButton];
	[_controlsView addSubview:_exitButton];
	[_controlsView addSubview:_shiftButton];
	[_controlsView addSubview:_commandButton];
	[_controlsView addSubview:_optionButton];
	[_controlsView addSubview:_controlButton];
	[_controlsView addSubview:_helperFunctionButton];
	[_controlsView addSubview:_rightMouseButton];
}

- (void)dealloc
{
    [super dealloc];
}

- (id)scroller
{
	return _scroller;
}

- (bool)areControlsVisible
{
	return _areControlsVisible;
}

-(void)updateControls
{
	[_delegate setStatusBarShowsProgress: false];

	CGRect frame = [self frame];
	
	if ([self getOrientationState] == kOrientationVertical)
		[_controlsView setFrame:CGRectMake(0, frame.size.height, frame.size.width, kControlsBarHeight)];
	else 
		[_controlsView setFrame:CGRectMake(0, frame.size.height+71, frame.size.width, kControlsBarHeight)];

	[UIView beginAnimations:nil];
	[UIView setAnimationDuration:0];

	frame = [_controlsView frame];
	frame.origin.y -= kControlsBarHeight;
	[_controlsView setFrame:frame];

		
	// This will start the animation.
	[UIView endAnimations];
	
	frame = [self frame];
	frame.size.height -= kControlsBarHeight;
//	[_scroller setFrame: frame];
//	_dbgtxt = [NSString stringWithFormat: @"%f,%f", [self frame].size.height, [self frame].size.width];
}

//! Either hides or shows the controls bar at the bottom of the screen
//! (in portrait orientation). The hiding or showing is animated.
- (void)showControls:(bool)show
{
	static bool shownonce = false;
	if (_areControlsVisible != show && !shownonce)
	{
		shownonce=YES;
		CGRect frame;
		
		[UIView beginAnimations:nil];
		[UIView setAnimationDuration:0.15f];

		if (_areControlsVisible)
		{
			// Hide the keyboard if it was in view.
			if (_isKeyboardVisible)
			{
				[self toggleKeyboard:nil];
			}
			
			// Hide controls
			frame = [_controlsView frame];
			frame.origin.y = [self frame].size.height;
			[_controlsView setFrame:frame];
			
			frame = [_scroller frame];
			frame.size.height += kControlsBarHeight;
			[_scroller setFrame:frame];
			_ipodScreenSize.height += kControlsBarHeight;
			
			// Hide the keyboard if it was in view.
			if (_isKeyboardVisible)
			{
				[self toggleKeyboard:nil];
			}
		}
		else
		{
		
			// Show controls
			frame = [_controlsView frame];
			frame.origin.y -= kControlsBarHeight;
			[_controlsView setFrame:frame];
			
			frame = [_scroller frame];
			frame.size.height -= kControlsBarHeight;
			[_scroller setFrame:frame];
			_ipodScreenSize.height -= kControlsBarHeight;
		}
		
		// This will start the animation.
		[UIView endAnimations];
		
		_areControlsVisible = show;
	}
}

- (float)orientationDegree
{
	return [_screenView getOrientationDeg];
}

- (void)toggleControls
{
	[self showControls:!_areControlsVisible];
}

- (CGPoint)topLeftVisiblePt
{
	return [_scroller bounds].origin;
}

- (void)changeViewPinnedToPoint:(CGPoint)ptPinned scale:(float)fScale orientation:(UIHardwareOrientation)wOrientationState force:(BOOL)bForce
{
	[_scroller changeViewPinnedToPoint:ptPinned scale:fScale orientation:wOrientationState force:bForce];
}

- (void)setStartupTopLeftPt:(CGPoint)pt
{
	_ptStartupTopLeft = pt;
}

- (void)dbg: (NSString*)txt
{
	if (_dbgtxtlbl)
	{
		[_dbgtxtlbl removeFromSuperview];
		[_dbgtxtlbl release];
	}			
	_dbgtxtlbl = [[UITextLabel alloc] initWithFrame:CGRectMake(5, 100, 280, 100)];
	[_dbgtxtlbl setFont:GSFontCreateWithName("VerdanaBold", 0, 9.0f)];
	[_dbgtxtlbl setCentersHorizontally: true];
	[_dbgtxtlbl setText: txt];
	[_dbgtxtlbl setWrapsText: YES];
	[self addSubview:_dbgtxtlbl];
}

- (void)toggleRemote: (id)sender
{
	if (!_isRemoteActive)
	{
		if (_isKeyboardVisible)
			[self toggleKeyboard:nil];

		if (_helpView)
			[_helpView dealloc];
		[self initRemote];
		[self addSubview:_helpView];
	}
	else
	{
		[_helpView removeFromSuperview];
	}
	_isRemoteActive=!_isRemoteActive;
	[_helperFunctionButton setNavBarButtonStyle:_isRemoteActive? 3 : 0];
}

- (void)initRemote
{
	_helpView = [[UIView alloc] initWithFrame: [_scroller frame]];
	[_helpView setOpaque:YES];
	[_helpView setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0.1f,0.1f,0.1f, 1)];

	CGRect frame = [_scroller frame];
	UIView *downloader = _helpView;

	const float kTextComponents[] = { .94, .94, .94, 1 };
	const float kTransparentComponents[] = { 0, 0, 1, 0 };
		
    CGColorSpaceRef rgbSpace = CGColorSpaceCreateDeviceRGB();
    CGColorRef textColorStatus = CGColorCreate(rgbSpace, kTextComponents);
    CGColorRef rgbTransparent = CGColorCreate(rgbSpace, kTransparentComponents);		
	CGColorSpaceRelease(rgbSpace);
		
	GSFontRef font = GSFontCreateWithName("Verdana", 0, 31.0f);
	GSFontRef fontArrows = GSFontCreateWithName("Verdana", 0, 0.0f);

	UIPushButton *aButton;
	int x1 = frame.size.width/5;
	int x2 = frame.size.width/2;
	int x3 = 4*frame.size.width/5;
	int y1 = frame.size.height/5;
	int y2 = frame.size.height/2;
	int y3 = 4*frame.size.height/5;
	int butwidth = 100;
	int butheight = 100;

/////////////////// 111111111111111111111111111111111111111111111111

	aButton = [[UIPushButton alloc] initWithTitle:@"Esc" autosizesToFit:NO];
	[aButton setTitleFont: font];
	[aButton setFrame:CGRectMake(x1 - butwidth/2, y1 - butheight/2, butwidth, butheight)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(sendESCKey:) forEvents:kUIControlEventMouseUpInside];
	[downloader addSubview:aButton];
	
	aButton = [[UIPushButton alloc] initWithImage:[UIImage imageNamed:@"up.png"]];
	[aButton setTitle: @"Up"];
	[aButton setTitleFont: fontArrows];
	[aButton setFrame:CGRectMake(x2 - 76/2, y1 - 76/2, 76, 76)];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(startSendingArrowKeys:) forEvents:kUIControlEventMouseDown];
	[aButton addTarget:self action:@selector(stopSendingArrowKeys:) forEvents:(kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)];
	[downloader addSubview:aButton];

	aButton = [[UIPushButton alloc] initWithTitle:@"Back" autosizesToFit:NO];
	[aButton setTitleFont: font];
	[aButton setFrame:CGRectMake(x3 - butwidth/2, y1 - butheight/2, butwidth, butheight)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(sendArrowKeys:) forEvents:kUIControlEventMouseUpInside];
	[downloader addSubview:aButton];

/////////////////// 222222222222222222222222222222222222222222222222

	aButton = [[UIPushButton alloc] initWithImage:[UIImage imageNamed:@"left.png"]];
	[aButton setTitle: @"Left"];
	[aButton setTitleFont: fontArrows];
	[aButton setFrame:CGRectMake(x1 - 76/2, y2 - 76/2, 76, 76)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(startSendingArrowKeys:) forEvents:kUIControlEventMouseDown];
	[aButton addTarget:self action:@selector(stopSendingArrowKeys:) forEvents:(kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)];
	[downloader addSubview:aButton];

	aButton = [[UIPushButton alloc] initWithImage:[UIImage imageNamed:@"ok.png"]];
	[aButton setTitleFont: fontArrows];
	[aButton setTitle: @"Enter"];
	[aButton setFrame:CGRectMake(x2 - 57/2, y2-53/2, 57, 53)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(startSendingArrowKeys:) forEvents:kUIControlEventMouseDown];
	[aButton addTarget:self action:@selector(stopSendingArrowKeys:) forEvents:(kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)];
	[downloader addSubview:aButton];

	aButton = [[UIPushButton alloc] initWithImage:[UIImage imageNamed:@"right.png"]];
	[aButton setTitle: @"Right"];
	[aButton setTitleFont: fontArrows];
	[aButton setFrame:CGRectMake(x3 - 76/2, y2 - 76/2, 76, 76)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(startSendingArrowKeys:) forEvents:kUIControlEventMouseDown];
	[aButton addTarget:self action:@selector(stopSendingArrowKeys:) forEvents:(kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)];
	[downloader addSubview:aButton];

/////////////////// 333333333333333333333333333333333333333333333333

	aButton = [[UIPushButton alloc] initWithTitle:@"Tab" autosizesToFit:NO];
	[aButton setTitleFont: font];
	[aButton setFrame:CGRectMake(x1-butwidth/2, y3 - butheight/2, butwidth, butheight)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(sendTabKey:) forEvents:kUIControlEventMouseUpInside];
	[downloader addSubview:aButton];
	
	aButton = [[UIPushButton alloc] initWithImage:[UIImage imageNamed:@"down.png"]];
	[aButton setTitle: @"Down"];
	[aButton setTitleFont: fontArrows];
	[aButton setFrame:CGRectMake(x2 - 76/2, y3 - 76/2, 76, 76)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(startSendingArrowKeys:) forEvents:kUIControlEventMouseDown];
	[aButton addTarget:self action:@selector(stopSendingArrowKeys:) forEvents:(kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)];
	[downloader addSubview:aButton];

	aButton = [[UIPushButton alloc] initWithTitle:@"Space" autosizesToFit:NO];
	[aButton setTitleFont: font];
	[aButton setFrame:CGRectMake(x3-butwidth/2, y3 - butheight/2, butwidth, butheight)];
	[aButton setDrawsShadow:YES];
	[aButton setDrawContentsCentered:YES];
	[aButton setShowPressFeedback:YES];
	[aButton addTarget:self action:@selector(sendArrowKeys:) forEvents:kUIControlEventMouseUpInside];
	[downloader addSubview:aButton];

	CFRelease(font);
}

- (void)toggleFitWidthHeight:(id)sender
{
	UIPushButton *pButton = (UIPushButton *)sender;	
	scaleSpecialTypes wScaleState = [self getScaleState], wScaleThisButton;

	if (sender == _fitWidthButton)
		wScaleThisButton = kScaleFitWidth;
	else if (sender == _fitHeightButton)
		wScaleThisButton = kScaleFitHeight;
	else if (sender == _fitWholeButton)
		wScaleThisButton = kScaleFitWidth | kScaleFitHeight;
	else if (sender == _fitNoneButton)
		wScaleThisButton = 0;
	[self setScaleState: wScaleThisButton];
	[self setOrientation: [self getOrientationState] bForce:true];
	if (sender != _fitNoneButton)
		[_scroller scrollPointVisibleAtTopLeft: CGPointMake(0,0)];
	NSLog(@"Got Event or Scale Change");
}


- (CGRect)scrollerFrame
{
	return [_scroller frame];
}

//! The toggle keyboard button has been pressed. This method assumes
//! the controls bar is visible.
- (void)toggleKeyboard:(id)sender
{
//	NSLog(@"toggling keyboard: old=%d", (int)_isKeyboardVisible);
	
	CGRect frame = [_scroller frame];
	
	if (_keyboardView == nil)
		_keyboardView = [UIKeyboardImpl sharedInstance];
	
	if (_isKeyboardVisible)
	{
		// Remove the keyboard view.
		[_keyboardView removeFromSuperview];
		[_keyTextLabel removeFromSuperview];
		[_keyTextLabel release];
		_keyTextLabel = nil;
		
		// Adjust scroller frame back to normal size (minus the controls bar).
		frame = [self bounds];
		frame.size.height -= kControlsBarHeight;
		[_scroller setFrame:frame];
	}
	else
	{
		if (_isRemoteActive)
			[self toggleRemote: nil];

		int keywidth;
		if ([self getOrientationState] != kOrientationVertical) 
		{
			keywidth = 480;
			[_keyboardView setSize:CGSizeMake(keywidth, 180)];
			[_keyboardView setOrigin:CGPointMake(0, frame.size.height - [_keyboardView frame].size.height)];
			[_keyboardView showLayout:[UIKeyboardLayoutQWERTYLandscape class]];
		}
		else
		{
			keywidth = 320;
			[_keyboardView setSize:CGSizeMake(keywidth, 216)];
			
			[_keyboardView setOrigin:CGPointMake(0, frame.size.height - [_keyboardView frame].size.height)];
			[_keyboardView showLayout:[UIKeyboardLayoutQWERTY class]];
		}

		// Adjust scroller frame so that its height is from below the system
		// status bar to the top of the keyboard.
		frame = [self bounds];
		frame.size.height = frame.size.height - kControlsBarHeight - [_keyboardView frame].size.height;
		[_scroller setFrame:frame];


		_keyTextLabel = [[UITextLabel alloc] initWithFrame:frame];
		[_keyTextLabel setFont:GSFontCreateWithName("Verdana", 0, 16.0f)];
		[_keyTextLabel setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,0,0, 1)];
		[_keyTextLabel setColor:GSColorCreateColorWithDeviceRGBA(1,1,1, 1)];
		[_keyTextLabel setCentersHorizontally: NO];
		[_keyTextLabel setWrapsText: YES];
		[_keyTextLabel setEllipsisStyle: kUITextLabelEllipsisLeading];
		[self addSubview:_keyTextLabel];
		_keyText = @"";

		
		// Add in the keyboard view.
		[self addSubview:_keyboardView];
//		[_keyboardView activate];
		
		// Set the delegate now that we have an active keyboard.
		[[UIKeyboardImpl activeInstance] setDelegate:self];
	}
	
	_isKeyboardVisible = !_isKeyboardVisible;
	[_keyboardButton setNavBarButtonStyle:_isKeyboardVisible? 3 : 0];
}

//! This message is received when the user has pressed the close connection
//! button.
- (void)closeConnection:(id)sender
{
	CGRect screenRect = [UIHardware fullScreenApplicationContentRect];
	screenRect.size.height+=20;
//	CGRect frame = CGRectMake(0.0f, 0.0f, 320, 460);
//	[_mainView setFrame:frame];
//	[_window setFrame:screenRect];
//	[self setOrientation: kOrientationVertical bForce:YES];

	// Hide the keyboard before closing.
	if (_isKeyboardVisible)
	{
		[self toggleKeyboard:nil];
	}
	
	if (_delegate && [_delegate respondsToSelector:@selector(closeConnection)])
	{
		[_delegate closeConnection];
	}
}


- (void)getHelp:(id)sender
{
	[self setOrientation: kOrientationVertical bForce:YES];
	[_delegate showWebPage:@"http://www.cs.cmu.edu/~jsherwan/projects/touchpad/controls.html" withTitle:@"Help" fromView:self];
	_browsingHelp = true;
}

- (void) alertSheet:(id)sheet buttonClicked:(int)button
{
	[sheet dismissAnimated:YES];
	[sheet release];

	if (button == 1)
		[_delegate openURL: [[NSURL alloc] initFileURLWithPath:@"http://www.touchpadpro.com/controls.html"]];
}

//! Handle the right mouse button being pressed.
//!
- (void)toggleRightMouse:(id)sender
{
//	bool useRight = ![_scroller useRightMouse];
//	[_rightMouseButton setNavBarButtonStyle:useRight ? 3 : 0];
//	[_scroller setUseRightMouse:useRight];
}

//! Handle one of the modifier key buttons being pressed.
//!
- (void)toggleModifierKey:(id)sender
{
	unsigned int modifier;
	if (sender == _shiftButton)
	{
		modifier = NSShiftKeyMask;
	}
	else if (sender == _commandButton)
	{
		modifier = NSCommandKeyMask;
	}
	else if (sender == _optionButton)
	{
		modifier = NSAlternateKeyMask;
	}
	else if (sender == _controlButton)
	{
		modifier = NSControlKeyMask;
	}
	else
	{
		// Unexpected sender.
		NSLog(@"Unexpected sender = %@", sender);
		return;
	}
	
	// Determine the new modifier mask.
	//! @todo This logic should be in EventFilter, not here.
	unsigned int currentModifiers = [_filter pressedModifiers];
	unsigned int newModifiers = currentModifiers ^ modifier;
	bool isPressed = newModifiers & modifier;
	
	NSLog(@"current=%x, new=%x, is=%d", currentModifiers, newModifiers, (int)isPressed);
	
	// Change the button color.
	[sender setNavBarButtonStyle:isPressed ? 3 : 0];
	
	// Queue the modifier changed event.
//	if (modifier == NSAlternateKeyMask)
//		[_scroller toggleAcceleration];
	[_filter flagsChanged:newModifiers];
}

//! Returns whether the first frame update has been received from the server.
//!
- (bool)isFirstDisplay
{
	return _isFirstDisplay;
}

- (id)delegate
{
	return _delegate;
}

- (void)setDelegate:(id)theDelegate
{
	_delegate = theDelegate;
}

- (RFBConnection *)connection;
{
	return _connection;
}

-(void)toggleViewOnly
{
	[_scroller toggleViewOnly];
}
//! This method is invoked before the VNCView is displayed to the user, so
//! that the controls on the controls bar can be properly enabled or disabled
//! based on their relevance if view only mode is enabled. For instance,
//! the keyboard and right mouse buttons should be disabled in view only mode
//! because the user cannot type or click remotely.
- (void)enableControlsForViewOnly:(bool)isViewOnly
{
	bool notViewOnly = !isViewOnly;

	if (isViewOnly)
		{
		[_keyboardButton removeFromSuperview];
		[_shiftButton removeFromSuperview];
		[_commandButton removeFromSuperview];
		[_optionButton removeFromSuperview];
		[_controlButton removeFromSuperview];
		[_rightMouseButton removeFromSuperview];
		[_delegate setStatusBarMode: kUIStatusBarBlack duration:0];
		}
	else
		{
		[_controlsView addSubview: _keyboardButton];
		[_controlsView addSubview: _shiftButton];
		[_controlsView addSubview: _commandButton];
		[_controlsView addSubview: _optionButton];
		[_controlsView addSubview: _controlButton];
		[_controlsView addSubview: _rightMouseButton];
		[_delegate setStatusBarMode: kUIStatusBarWhite duration:0];
		}
/*	
	[_keyboardButton setEnabled:notViewOnly];
	[_shiftButton setEnabled:notViewOnly];
	[_commandButton setEnabled:notViewOnly];
	[_optionButton setEnabled:notViewOnly];
	[_controlButton setEnabled:notViewOnly];
	[_rightMouseButton setEnabled:notViewOnly];
*/
	
}

//! The frame buffer has been created by the connection object and is
//! being passed to us. We pass it along to the underlying content view
//! that does the actual drawing.
- (void)setFrameBuffer:(id)aBuffer;
{
	[_screenView setFrameBuffer:aBuffer];
}

//! Either a new connection is being set or the connection is being cleared
//! because it was closed. When a new connection is being set, we hook up
//! some objects to each other, such as the EventFilter.
- (void)setConnection:(RFBConnection *)connection
{
    _connection = connection;
	if (_connection)
	{
		_isFirstDisplay = false;
		[self initControlsBar];
		_filter = [_connection eventFilter];
		[_filter setView:_scroller];
		[_scroller setEventFilter:_filter];
		[_scroller setViewOnly:[_connection viewOnly]];
		[_scroller scrollPointVisibleAtTopLeft:CGPointMake(0, 0)];
		[_screenView setNeedsDisplay];
		
		// Enable or disable controls depending on view only mode.
		[self enableControlsForViewOnly:[_connection viewOnly]];
	}
	else
	{
		// The connection was closed.
		_filter = nil;
		[_scroller setEventFilter:nil];
		[_scroller cleanUpMouseTracks];
		[_screenView setFrameBuffer:nil];
		[_screenView setOrientationState:0];
		// Get the screen view to redraw itself in black.
		[_screenView setNeedsDisplay];
	}
}

- (UIHardwareOrientation)getOrientationState;
{
	return [_screenView getOrientationState];
}


- (scaleSpecialTypes)getScaleState
{
	return _scaleState;
}

- (void)setScaleState:(scaleSpecialTypes)wScaleState
{
	_scaleState = wScaleState;
}

- (float)scaleFitCurrentScreen: (scaleSpecialTypes) wScaleState
{
		float dx,dy, wScaleX, wScaleY, wScale = 10;
		
		NSLog(@"In scale fit");
		switch ([self getOrientationState])
		{
			case kOrientationVerticalUpsideDown:
			case kOrientationVertical:
				dx = _ipodScreenSize.width;
				dy = _ipodScreenSize.height;
				break;
				
			default:
			case kOrientationHorizontalLeft:
			case kOrientationHorizontalRight:
				dx = _ipodScreenSize.height;
				dy = _ipodScreenSize.width;
				break;
		}
		
		wScaleX = dx / _vncScreenSize.width;
		wScaleY = dy / _vncScreenSize.height;
		switch (wScaleState)
		{
			case kScaleFitWhole:  // fit Whole Screen on IPod
				wScale = wScaleX < wScaleY ? wScaleX : wScaleY;
				break;

			case kScaleFitWidth:  // fit Width
				wScale = wScaleX;
				break;

			case kScaleFitHeight: // fit Height
				wScale = wScaleY;
                break;
		}
	NSLog(@"Out scale fit");
	return wScale;
}

- (void)setScalePercent:(float)wScale
{
	if (_scaleState != kScaleFitNone)
    {
		wScale = [self scaleFitCurrentScreen: _scaleState];
	}
//	NSLog(@"New Scale = %f", wScale);
	[_screenView setScalePercent: wScale];
}

- (CGRect)getFrame
{
	return [_screenView getFrame];
}

- (float)getScalePercent
{
	return [_screenView getScalePercent];
}

- (CGPoint)getIPodScreenPoint:(CGRect)r bounds:(CGRect)bounds
{
	return [_screenView getIPodScreenPoint: r bounds:bounds];
}

- (void)finishedBrowsingHelp
{
	_browsingHelp = false;
}

- (void)setOrientation:(UIHardwareOrientation)wOrientation bForce:(int)bForce
{
	CGSize vncScreenSize = _vncScreenSize;
	CGSize newRemoteSize;

	if ([_scroller acceleration] || !_connection || _browsingHelp)
		return;

	if(!(wOrientation == kOrientationVertical // || wOrientation == kOrientationVerticalUpsideDown 
		|| wOrientation == kOrientationHorizontalLeft || wOrientation == kOrientationHorizontalRight))
	{
		return;
	}

	[_delegate setStatusBarMode:kUIStatusBarWhite orientation:wOrientation==kOrientationVertical?0:wOrientation==kOrientationHorizontalLeft?90:-90 duration:0.1f];

	NSLog(@"VNC Screen Size  = %f %f", vncScreenSize.width, vncScreenSize.height);
	if (bForce || (_connection && wOrientation != [_screenView getOrientationState]))
	{
		UIHardwareOrientation oldOrientation = [_screenView getOrientationState];
//		NSLog(@"Orientation Change %d", wOrientation);

		[_screenView setOrientationState:wOrientation];
	
		if (wOrientation == kOrientationVertical || wOrientation == kOrientationVerticalUpsideDown)
		{
			newRemoteSize = vncScreenSize;
			if (!bForce)
				{
				if (oldOrientation == kOrientationHorizontalLeft || oldOrientation == kOrientationHorizontalRight)
					[self showControls: _savedControlShowState];
				}
		}
		else
		{
			newRemoteSize.width = vncScreenSize.height;
			newRemoteSize.height = vncScreenSize.width;
			if (!bForce)
				{
				_savedControlShowState = _areControlsVisible;
				[self showControls:0];
				}
		}

//		CGRect frame = [_controlsView frame];
//		frame.origin.y += kControlsBarHeight;
//		[_controlsView setFrame:frame];
		bool activateRemote=NO;
		if (_isRemoteActive)
		{
			[self toggleRemote: nil];
			activateRemote=YES;
		}
		CGRect changeself;
//		[_scroller setBackgroundColor:GSColorCreateColorWithDeviceRGBA(255,0,0, 0.5)];
//		[self setBackgroundColor:GSColorCreateColorWithDeviceRGBA(0,255,0, 0.5)];

		CGRect oldscrollerframe = [_mainView frame];
		CGRect oldscrollerbounds = [_mainView bounds];
		CGRect oldselfframe = [self frame];
		CGRect oldselfbounds = [self bounds];
		float sbheight = [UIHardware statusBarHeight];
		CGRect futureframe = CGRectMake(
						wOrientation==kOrientationVertical?0.0f:0.0f,
						wOrientation==kOrientationVertical?0.0f:0.0f,
						wOrientation==kOrientationVertical?[UIHardware mainScreenSize].width:[UIHardware mainScreenSize].height,
						wOrientation==kOrientationVertical?[UIHardware mainScreenSize].height:[UIHardware mainScreenSize].width);
	[_delegate setUIOrientation: wOrientation];
	CGRect screenframe = CGRectMake(0.0f, 0.0f, [UIHardware mainScreenSize].width, [UIHardware mainScreenSize].height);
	CGRect mainframe   = CGRectMake(0.0f, 0.0f, [UIHardware mainScreenSize].width, [UIHardware mainScreenSize].height);
	if (wOrientation==kOrientationVertical)
	{
		//screenframe = [UIHardware fullScreenApplicationContentRect];
//		screenframe.origin.y = sbheight;
//		screenframe.size.height -=sbheight;
//		mainframe.size.height-=sbheight;
	}
	else 
	{
//		screenframe.size.width -=sbheight;
//		mainframe.size.width -=sbheight;
//		if (wOrientation==kOrientationHorizontalRight)
//			screenframe.origin.x = sbheight;
	}	
	bool keyboardWasVisible = false;

	[UIView beginAnimations:nil];
	[UIView setAnimationDuration:0.1f];

	NSString *savedtext;
	if (_isKeyboardVisible)
	{
		savedtext = [NSString stringWithFormat: @"%@", _keyText];
		[self toggleKeyboard:nil];
		keyboardWasVisible = YES;
	}

		[self setBounds: futureframe];
		[self rotateToDegrees: wOrientation==kOrientationVertical?0:wOrientation==kOrientationHorizontalLeft?90:-90];
		[_window setFrame:screenframe];
		[_mainView setFrame: mainframe];

		CGRect controlsframe = [self bounds];
		controlsframe.origin.y = controlsframe.size.height - kControlsBarHeight;
		controlsframe.size.height = kControlsBarHeight;
		[_controlsView setFrame: controlsframe];
		if (oldOrientation == kOrientationVertical && wOrientation != kOrientationVertical && !_isStretched)
		{
			[self stretch:_keyboardButton big:YES];
			[self stretch:_exitButton big:YES];
			[self stretch:_shiftButton big:YES];
			[self stretch:_commandButton big:YES];
			[self stretch:_optionButton big:YES];
			[self stretch:_controlButton big:YES];
			[self stretch:_helperFunctionButton big:YES];
			[self stretch:_rightMouseButton big:YES];
			_isStretched = YES;
		}
		else if (wOrientation == kOrientationVertical && _isStretched)
		{
			[self stretch:_keyboardButton big:NO];
			[self stretch:_exitButton big:NO];
			[self stretch:_shiftButton big:NO];
			[self stretch:_commandButton big:NO];
			[self stretch:_optionButton big:NO];
			[self stretch:_controlButton big:NO];
			[self stretch:_helperFunctionButton big:NO];
			[self stretch:_rightMouseButton big:NO];
			_isStretched = NO;
		}
		
		

		CGRect scrollerframe = [self bounds];
		scrollerframe.size.height-=kControlsBarHeight;
		[_scroller setFrame: scrollerframe];

	if (keyboardWasVisible)
	{
		[self toggleKeyboard:nil];
		_keyText = [NSString stringWithFormat: @"%@", savedtext];
		[self showTypedText];
	}


	[UIView endAnimations];



		CGRect newscrollerframe = [_mainView frame];
		CGRect newscrollerbounds = [_mainView bounds];
		CGRect newselfframe = [self frame];
		CGRect newselfbounds = [self bounds];
	if (NO)
			[self dbg: [NSString stringWithFormat: @"scrof(%.0f%,%.0f%)(%.0f%,%.0f%), scrob(%.0f%,%.0f%),(%.0f%,%.0f%), scrnf(%.0f%,%.0f%),(%.0f%,%.0f%), scrnb(%.0f%,%.0f%),(%.0f%,%.0f%), selof(%.0f%,%.0f%)(%.0f%,%.0f%), selob(%.0f%,%.0f%),(%.0f%,%.0f%), selnf(%.0f%,%.0f%),(%.0f%,%.0f%), selnb(%.0f%,%.0f%),(%.0f%,%.0f%)", 
			oldscrollerframe.origin.x, oldscrollerframe.origin.y, oldscrollerframe.size.width, oldscrollerframe.size.height, 
			oldscrollerbounds.origin.x, oldscrollerbounds.origin.y, oldscrollerbounds.size.width, oldscrollerbounds.size.height, 
			newscrollerframe.origin.x, newscrollerframe.origin.y, newscrollerframe.size.width, newscrollerframe.size.height, 
			newscrollerbounds.origin.x, newscrollerbounds.origin.y, newscrollerbounds.size.width, newscrollerbounds.size.height,
			oldselfframe.origin.x, oldselfframe.origin.y, oldselfframe.size.width, oldselfframe.size.height, 
			oldselfbounds.origin.x, oldselfbounds.origin.y, oldselfbounds.size.width, oldselfbounds.size.height, 
			newselfframe.origin.x, newselfframe.origin.y, newselfframe.size.width, newselfframe.size.height, 
			newselfbounds.origin.x, newselfbounds.origin.y, newselfbounds.size.width, newselfbounds.size.height
			]];

//		[self dbg: [NSString stringWithFormat: @"oframe(%3.0f%,%3.0f%)(%3.0f%,%3.0f%), obound(%3.0f%,%3.0f%),(%3.0f%,%3.0f%), nframe(%3.0f%,%3.0f%),(%3.0f%,%3.0f%), nbound(%3.0f%,%3.0f%),(%3.0f%,%3.0f%)", oldframe.size.width, oldframe.size.height, oldbounds.size.width, oldbounds.size.height, newframe.size.width, newframe.size.height, newbounds.size.width, newbounds.size.height]];
//		[self dbg: [NSString stringWithFormat: @"%3.0f%,%3.0f%,%3.0f%,%3.0f%,\n %3.0f%,%3.0f%,%3.0f%,%3.0f%", oldbounds.origin.x, oldbounds.origin.y, newframe.origin.x, newframe.origin.y, newbounds.origin.x, newbounds.origin.y]];
		
//		[self updateControls];
		if (activateRemote)
		{
			[self toggleRemote: nil];
		}

		if ([self getScaleState] != kScaleFitNone)
		{
			[self setScalePercent: 0];
		}
		float fUnscale = [_screenView getScalePercent];

		CGRect bounds = CGRectMake(0, 0, vncScreenSize.width, vncScreenSize.height);
		[_screenView setBounds: bounds];

		CGAffineTransform matrix = CGAffineTransformRotate(CGAffineTransformMakeScale(0 - fUnscale, fUnscale), 
				([_screenView getOrientationDeg])  * M_PI / 180.0f);
		[_filter setBackToVNCTransform: CGAffineTransformInvert(matrix)];
		[_filter setOrientation: wOrientation];
		[_filter firstMouseAt];

		newRemoteSize.width = newRemoteSize.width * [_screenView getScalePercent];
		newRemoteSize.height = newRemoteSize.height  * [_screenView getScalePercent];

//		CGRect newframe = [_scroller frame];
//		CGRect newbounds = [_scroller bounds];
//		[self dbg: [NSString stringWithFormat: @"%3.0f%,%3.0f%,%3.0f%,%3.0f%, %3.0f%,%3.0f%,%3.0f%,%3.0f%", oldframe.size.width, oldframe.size.height, oldbounds.size.width, oldbounds.size.height, newframe.size.width, newframe.size.height, newbounds.size.width, newbounds.size.height]];

//		NSLog(@"New Screen View = %f %f", newRemoteSize.width, newRemoteSize.height);
//		Animate if special double click zoom
//		[_screenView setRemoteDisplaySize:newRemoteSize animate:bForce == 2 ? YES : !bForce];
	
		// Reset our scroller's content size.
//		[_scroller setContentSize:newRemoteSize];
	}
}

- (void)stretch: (UINavBarButton*)pb big:(bool)b
{
	CGRect f = [pb frame];
	f.origin.x *= b ? 1.5 : 1.0/1.5;
//	f.size.width *= b ? 1.5 : 1.0/1.5;
	[pb setFrame: f];
}

- (void)setWindow: (UIWindow*)w
{
	_window = w;
}

- (void)setMainView: (UIView*)u
{
	_mainView = u;
}

- (void)setRemoteComputerName:(NSString *)name
{
	_remoteComputerName = name;
}

- (void)setRemoteDisplaySize:(CGSize)remoteSize
{
	//	NSLog(@"Setting VNC screen size %f %f", remoteSize.width, remoteSize.height);

	// ******************************************************************************
	// BAD BAD BAD IPHONE BUG WITH DEVICE CONTEXT ONLY ABLE to reach 1024 then crash 
	// ******************************************************************************
//	_vncScreenSize = CGSizeMake(remoteSize.width, MIN(((2*1024*1024) / remoteSize.width), remoteSize.height));
	_vncScreenSize = CGSizeMake(1,1);
	[self setScaleState: kScaleFitNone];
	[self setOrientation: kOrientationVertical bForce:false];
}

//! The connection object is telling us that a region of the framebuffer
//! needs to be redrawn.
- (void)displayFromBuffer:(CGRect)aRect
{	
	[_screenView displayFromBuffer:aRect];
	
	// If this is our first display update then Transition to the VNC server screen
	if (!_isFirstDisplay)
	{
		_isFirstDisplay = true;
		[_scroller scrollPointVisibleAtTopLeft:_ptStartupTopLeft];
		[_delegate gotFirstFullScreenTransitionNow];
	}
}

//! This method is supposed to draw a list of rectangles. Unfortunately, the UIKit
//! doesn't seem to have an equivalent to lockFocus/unlockFocus, so there's no way
//! to get a drawing context outside of the regular draw methods. But it seems
//! that this method isn't called much (never seen it once), so it's not a big deal.
- (void)drawRectList:(id)aList
{
	NSLog(@"VNCView:drawRectList:%@", aList);
	
	// XXX this may not be cool!
//    [self lockFocus];
//    [aList drawRectsInRect:[self bounds]];
//    [self unlockFocus];
}

- (CGRect)contentRect
{
	return [_screenView bounds];
}

#pragma mark ** UIKeyboardInput **

- (void)deleteBackward
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	
	if ([_keyText length] > 0)
		_keyText = [_keyText substringToIndex: [_keyText length] - 1];
	[self showTypedText];
	[_filter keyTyped:@"\x007f"];
}

- (void)insertText:(id)text
{
//	NSLog(@"%s:%@", __PRETTY_FUNCTION__, text);

	if ([text characterAtIndex: 0] == '\n')
		[self clearTypedText];
	
	_keyText=[NSString stringWithFormat: @"%@%@", _keyText, text];
	[self showTypedText];
	[_filter keyTyped:text];
}

- (void)showTypedText
{
	int textlength = [_keyText length];
//	NSLog(@"key dbg %d", MAX(0, textlength - 5));
	[_keyTextLabel setText: _keyText];//[_keyText substringFromIndex: MAX(0, textlength - 5)]];
}

- (void)clearTypedText
{
	_keyText = @"";
	[self showTypedText];
}

- (void)replaceCurrentWordWithText:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)setMarkedText:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (id)markedText
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (unsigned short)characterInRelationToCaretSelection:(int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0; //L' ';
}

- (unsigned short)characterBeforeCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0; //L' ';
}

- (unsigned short)characterAfterCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0; //L' ';
}

- (struct __GSFont *)fontForCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return [UIPushButton defaultFont];
}

- (struct CGColor *)textColorForCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return [UITextTraits defaultCaretColor];
}

- (struct CGRect)rectContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return CGRectMake(0,0,0,0);
}

- (id)wordRangeContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (id)wordContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (id)wordInRange:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (void)expandSelectionToStartOfWordContainingCaretSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (int)wordOffsetInRange:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return 0;
}

- (BOOL)spaceFollowsWordInRange:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (id)previousNGrams:(unsigned int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return nil;
}

- (struct _NSRange)selectionRange
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NSMakeRange(0, 0);
}

- (BOOL)hasSelection
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)selectionAtDocumentStart
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)selectionAtSentenceStart
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)selectionAtWordStart
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)rangeAtSentenceStart:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (void)markCurrentWordForAutoCorrection:(id)fp8 correction:(id)fp12
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)moveBackward:(unsigned int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)moveForward:(unsigned int)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)selectAll
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)setText:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (id)text
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return @"";
}

- (void)updateSelectionWithPoint:(struct CGPoint)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (void)setCaretChangeListener:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (struct CGRect)caretRect
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return CGRectMake(0,0,0,0);
}

- (struct CGRect)convertCaretRect:(struct CGRect)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return CGRectMake(0,0,0,0);
}

- (id)keyboardInputView
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return self;
}

- (id)textTraits
{
	UITextTraits * traits = [UITextTraits defaultTraits];
	[traits setAutoCapsType:0];	//?
	[traits setAutoCorrectionType:0];	//?
	[traits setAutoEnablesReturnKey:NO];
	return traits;
}

- (BOOL)isShowingPlaceholder
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (void)setupPlaceholderTextIfNeeded
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
}

- (BOOL)isProxyFor:(id)fp8
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	return NO;
}

- (BOOL)interceptKeyEvent:(GSEventRef)theEvent
{
//	NSLog(@"%s", __PRETTY_FUNCTION__);
	
//	unsigned eventType = GSEventGetType(theEvent);
//	unsigned subType = GSEventGetSubType(theEvent);
//	
//	NSLog(@"  type=%d; subtype=%d", eventType, subType);
//	
//	switch (eventType)
//	{
//		// key down
//		case 10:
//			[_filter keyDown:theEvent];
//			break;
//		
//		// key up
//		case 11:
//			[_filter keyUp:theEvent];
//			break;
//	}
	
	return NO;
}

/*
//These Methods track delegate calls made to the application
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector 
{
	NSLog(@"Requested method for selector: %@", NSStringFromSelector(selector));
	return [super methodSignatureForSelector:selector];
}

- (BOOL)respondsToSelector:(SEL)aSelector 
{
	NSLog(@"Request for selector: %@", NSStringFromSelector(aSelector));
	return [super respondsToSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{
	NSLog(@"Called from: %@", NSStringFromSelector([anInvocation selector]));
	[super forwardInvocation:anInvocation];
}
*/
@end
